package com.kakarote.hrm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.kakarote.core.common.Result;
import com.kakarote.core.common.enums.SystemCodeEnum;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.entity.FileEntity;
import com.kakarote.core.feign.admin.service.AdminFileService;
import com.kakarote.core.feign.admin.service.AdminService;
import com.kakarote.core.servlet.BaseServiceImpl;
import com.kakarote.hrm.constant.EmployeeFileType;
import com.kakarote.hrm.constant.HrmActionBehaviorEnum;
import com.kakarote.hrm.entity.BO.AddFileBO;
import com.kakarote.hrm.entity.BO.QueryFileBySubTypeBO;
import com.kakarote.hrm.entity.PO.HrmEmployee;
import com.kakarote.hrm.entity.PO.HrmEmployeeFile;
import com.kakarote.hrm.entity.VO.EmployeeFileVo;
import com.kakarote.hrm.mapper.HrmEmployeeFileMapper;
import com.kakarote.hrm.service.IHrmEmployeeFileService;
import com.kakarote.hrm.service.IHrmEmployeeService;
import com.kakarote.hrm.service.actionrecord.impl.EmployeeActionRecordServiceImpl;
import net.lingala.zip4j.ZipFile;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;

/**
 * <p>
 * 员工附件表 服务实现类
 * </p>
 *
 * @author huangmingbo
 * @since 2020-05-12
 */
@Service
public class HrmEmployeeFileServiceImpl extends BaseServiceImpl<HrmEmployeeFileMapper, HrmEmployeeFile> implements IHrmEmployeeFileService {

    @Autowired
    private HrmEmployeeFileMapper employeeFileMapper;

    @Autowired
    private AdminFileService adminFileService;
    @Autowired
    private AdminService adminService;
    @Autowired
    private IHrmEmployeeService employeeService;

    @Resource
    private EmployeeActionRecordServiceImpl employeeActionRecordService;

    @Override
    public Map<String, Object> queryFileNum(Long employeeId) {
        return employeeFileMapper.queryFileNum(employeeId);
    }

    @Override
    public List<HrmEmployeeFile> queryFileBySubType(QueryFileBySubTypeBO queryFileBySubTypeBO) {
        List<HrmEmployeeFile> list = lambdaQuery().eq(HrmEmployeeFile::getEmployeeId, queryFileBySubTypeBO.getEmployeeId())
                .eq(HrmEmployeeFile::getSubType, queryFileBySubTypeBO.getSubType())
                .list();
        list.forEach(employeeFile -> {
            employeeFile.setFile(adminFileService.queryById(Long.valueOf(employeeFile.getFileId())).getData());
        });
        return list;
    }

    @Override
    public void addFile(AddFileBO addFileBO) {
        HrmEmployeeFile employeeFile = BeanUtil.copyProperties(addFileBO, HrmEmployeeFile.class);
        save(employeeFile);
        if (employeeFile.getSubType()  == EmployeeFileType.PERSONAL_ID_PHOTO.getValue()) {
            HrmEmployee employee = employeeService.getById(employeeFile.getEmployeeId());
            String fileId = employeeFile.getFileId();
            FileEntity data = adminFileService.queryById(Long.valueOf(fileId)).getData();
            adminService.updateUserAvatarPathByUserName(employee.getMobile(),data.getUrl());
        }
        employeeActionRecordService.addFileRecord(employeeFile, HrmActionBehaviorEnum.ADD);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteFile(Long employeeFileId) {
        HrmEmployeeFile employeeFile = getById(employeeFileId);
        Long fileId = Long.valueOf(employeeFile.getFileId());
//        adminFileService.delete(fileId);
        if (employeeFile.getSubType()  == EmployeeFileType.PERSONAL_ID_PHOTO.getValue()) {
            HrmEmployee employee = employeeService.getById(employeeFile.getEmployeeId());
            adminService.updateUserAvatarPathByUserName(employee.getMobile(),null);
        }
        removeById(employeeFileId);
        employeeActionRecordService.addFileRecord(employeeFile, HrmActionBehaviorEnum.DELETE);
    }

    @Override
    public void materialExportZip(HttpServletResponse response, Long employeeId, List<Integer> typeList) {
        if (employeeId == null || typeList == null || typeList.isEmpty()) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }
        //员工附件
        List<EmployeeFileVo> fileList = employeeFileMapper.queryEmployeeFileList(employeeId, typeList);
        if (fileList != null && !fileList.isEmpty()) {
            //附件上传路径
            Map<Integer, String> mapResult = adminFileService.queryFilePath().getData();
            // 压缩文件路径
            String outputZipPath = mapResult.get(com.kakarote.core.entity.UploadEntity.PRIVATE_KEY) + UUID.randomUUID().toString() + ".zip";
            try {
                //设置参数
                ZipParameters parameters = new ZipParameters();
                //设置压缩密码
                parameters.setEncryptionMethod(EncryptionMethod.AES);
                //设置压缩方式.
                parameters.setCompressionMethod(CompressionMethod.DEFLATE);
                //设置压缩级别,默认为0（即不压缩）
                parameters.setCompressionLevel(CompressionLevel.NORMAL);
                //设置加密文件
                parameters.setEncryptFiles(true);
                
                // 创建 ZipFile 对象，指定输出压缩文件路径
                // TODO 设置压缩密码
                ZipFile zipFile = new ZipFile(outputZipPath, "123456".toCharArray());

                // 将文件添加到压缩包
                for (EmployeeFileVo file : fileList) {
                    // 指定文件夹路径（在压缩包内）
                    String folderInZip = EmployeeFileType.parseName(file.getSubType()) + "/";
                    File empFile;
                    if (file.getIsPublic() == 1) {
                        empFile = new File(mapResult.get(file.getIsPublic()) + file.getFilePath());
                    } else {
                        empFile = new File(mapResult.get(file.getIsPublic()) + file.getFilePath());
                    }
                    parameters.setFileNameInZip(folderInZip + empFile.getName());
                    zipFile.addFile(empFile, parameters);
                }
                System.out.println("加密压缩包已创建: " + outputZipPath);

                InputStream fis = new BufferedInputStream(Files.newInputStream(Paths.get(outputZipPath)));
                String fileName = URLEncoder.encode("员工附件", "utf-8");
                response.setCharacterEncoding("UTF-8");
                response.setHeader("Content-Disposition", "attachment; filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));
                response.setContentLength((int) zipFile.getFile().length());
                response.setContentType("application/zip");
                BufferedInputStream buff = new BufferedInputStream(fis);
                byte[] b = new byte[1024];
                long k = 0;
                OutputStream myout = response.getOutputStream();
                // 开始循环下载
                while (k < zipFile.getFile().length()) {
                    int j = buff.read(b, 0, 1024);
                    k += j;
                    myout.write(b, 0, j);
                }
                myout.flush();
                buff.close();
                zipFile.getFile().delete();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void fileExportZip(HttpServletResponse response, List<Long> fileIdList) {
        if (fileIdList.isEmpty()) {
            throw new CrmException(SystemCodeEnum.SYSTEM_NO_VALID);
        }
        Result<List<FileEntity>> listResult = adminFileService.queryByIds(fileIdList);
        if (listResult.hasSuccess() && listResult.getData() != null && !listResult.getData().isEmpty()){
            //员工文件
            List<FileEntity> fileList = listResult.getData();
            //附件上传路径
            Map<Integer, String> mapResult = adminFileService.queryFilePath().getData();
            // 压缩文件路径
            String outputZipPath = mapResult.get(com.kakarote.core.entity.UploadEntity.PRIVATE_KEY) + UUID.randomUUID().toString() + ".zip";
            try {
                //设置参数
                ZipParameters parameters = new ZipParameters();
                //设置压缩密码
                parameters.setEncryptionMethod(EncryptionMethod.AES);
                //设置压缩方式.
                parameters.setCompressionMethod(CompressionMethod.DEFLATE);
                //设置压缩级别,默认为0（即不压缩）
                parameters.setCompressionLevel(CompressionLevel.NORMAL);
                //设置加密文件
                parameters.setEncryptFiles(true);

                // 创建 ZipFile 对象，指定输出压缩文件路径
                // TODO 设置压缩密码
                ZipFile zipFile = new ZipFile(outputZipPath, "123456".toCharArray());

                // 将文件添加到压缩包
                for (FileEntity file : fileList) {
                    // 指定文件夹路径（在压缩包内）
                    File empFile;
                    if (file.getIsPublic() == 1) {
                        empFile = new File(mapResult.get(file.getIsPublic()) + file.getPath());
                    } else {
                        empFile = new File(mapResult.get(file.getIsPublic()) + file.getPath());
                    }
                    zipFile.addFile(empFile, parameters);
                }
                System.out.println("加密压缩包已创建: " + outputZipPath);

                InputStream fis = new BufferedInputStream(Files.newInputStream(Paths.get(outputZipPath)));
                String fileName = URLEncoder.encode("员工附件", "utf-8");
                response.setCharacterEncoding("UTF-8");
                response.setHeader("Content-Disposition", "attachment; filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));
                response.setContentLength((int) zipFile.getFile().length());
                response.setContentType("application/zip");
                BufferedInputStream buff = new BufferedInputStream(fis);
                byte[] b = new byte[1024];
                long k = 0;
                OutputStream myout = response.getOutputStream();
                // 开始循环下载
                while (k < zipFile.getFile().length()) {
                    int j = buff.read(b, 0, 1024);
                    k += j;
                    myout.write(b, 0, j);
                }
                myout.flush();
                buff.close();
                zipFile.getFile().delete();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }

    @Override
    public int deleteIdPhotoFile(HrmEmployeeFile hrmEmployeeFile) {
        return employeeFileMapper.deleteIdPhotoFile(hrmEmployeeFile);
    }
}
